package com.threeti.mecool.web.controller;

import com.threeti.mecool.core.application.SearchService;
import com.threeti.mecool.core.application.acl.EmployeeService;
import com.threeti.mecool.core.application.acl.UserService;
import com.threeti.mecool.core.application.basicdata.BasicDataService;
import com.threeti.mecool.core.application.project.ProjectService;
import com.threeti.mecool.core.domain.model.CommonKVT;
import com.threeti.mecool.core.domain.model.Hint;
import com.threeti.mecool.core.domain.model.HintKey;
import com.threeti.mecool.core.domain.model.acl.OrgnizationEmployee;
import com.threeti.mecool.core.domain.model.acl.User;
import com.threeti.mecool.core.domain.model.basicdata.Brand;
import com.threeti.mecool.core.domain.model.basicdata.BrandCategory;
import com.threeti.mecool.core.domain.model.basicdata.Product;
import com.threeti.mecool.core.domain.model.basicdata.ProjectProductData;
import com.threeti.mecool.core.domain.model.basicdata.biz.ChannelSync;
import com.threeti.mecool.core.domain.model.plan.ProjectCriticalJob;
import com.threeti.mecool.core.domain.model.plan.pojo.Job;
import com.threeti.mecool.core.domain.model.project.*;
import com.threeti.mecool.core.infrastructure.persistence.CommonKVTRepository;
import com.threeti.mecool.core.infrastructure.persistence.basicdata.biz.ChannelSyncRepository;
import com.threeti.mecool.core.infrastructure.persistence.plan.ProjectCriticalJobRepository;
import com.threeti.mecool.core.infrastructure.persistence.project.*;
import com.threeti.mecool.core.util.ExceptionHelper;
import com.threeti.mecool.framework.util.Lists;
import com.threeti.mecool.framework.util.Maps;
import com.threeti.mecool.framework.util.PageHandler;
import com.threeti.mecool.legacy.domain.model.basicdata.*;
import com.threeti.mecool.legacy.domain.model.basicdata.biz.PosKindLegacy;
import com.threeti.mecool.legacy.domain.model.basicdata.biz.PosSysTypeLegacy;
import com.threeti.mecool.legacy.domain.model.basicdata.biz.SalesLegacy;
import com.threeti.mecool.legacy.infrastructure.persistence.*;
import com.threeti.mecool.shared.util.TreeNodeWithChilds;
import com.threeti.mecool.web.assembler.ProjectAssembler;
import com.threeti.mecool.web.form.ProjectForm;
import com.threeti.mecool.web.util.JsTreeDataUtil;
import com.threeti.mecool.web.util.JsTreeDataUtil.MapDataAssembling;
import com.threeti.mecool.web.util.RequestUtil;
import com.threeti.mecool.web.util.WebResponse;
import org.apache.commons.lang.time.DateUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

@Controller
@RequestMapping("/project")
public class ProjectController {

    public static final Logger logger = LoggerFactory.getLogger(ProjectController.class);

    @Autowired
    private ProjectRepository projectRepo;

    @Autowired
    private CustomerLegacyRepository customerRepo;

    @Autowired
    private ProjectCategoryRepository projectCatRepo;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private ProjectStoreRepository projectStoreRepository;

    @Autowired
    BasicDataService basicService;

    @Autowired
    private UserService userService;

    @Autowired
    private ProjectEmployeeRepository projectEmployeeRepository;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private ProjectSalesPromoterRepository projSalesPromRepo;

    @Autowired
    private SalesLegacyRepository salesLegacyRepository;

    @Autowired
    private ProjectCriticalJobRepository projectCriticalJobRepository;

    @Autowired
    private ChannelSyncRepository channelSyncRepo;

    @Autowired
    private SearchService searchService;

    @Autowired
    private PosKindLegacyRepository posKindLegacyRepository;

    @Autowired
    private PosSysTypeLegacyRepository posSysTypeLegacyRepository;

    @Autowired
    private AdminDivisionLegacyRepository adminDivisionLegacyRepository;

    @Autowired
    private ProjectSalesPromoterRepository projSalesRepo;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    @Autowired
    private ObjectMapper jsonMapper;

    @Autowired
    private ProjectSellingUploadRepository projectSellingUploadRepository;

    @Autowired
    private CommonKVTRepository commonKVTRepository;

    @Autowired
    private Hint hint;

    @Autowired
    private SellingUpload sellingUpload;

    @RequestMapping(value = "/projectList.html")
    public void projectList(ProjectForm projForm) {
        projForm.setProjectCategories(projectCatRepo.findAll());
    }

    @RequestMapping(value = "/projectListData.html")
    public void projectListData(ProjectForm projForm, Pageable pageable, Map modelMap) {
        try {
            User user = userService.getCurrentUserWithPermissionRoleAndEntries();
            Page<Project> results = projectRepo.findAll(ProjectAssembler.toCriteria(projectService, user, projForm), pageable);
            PageHandler p = new PageHandler(pageable.getPageNumber(), Long.valueOf(results.getTotalElements()).intValue(),
                    pageable.getPageSize(), results.getContent());
            modelMap.put("page", p);
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    @RequestMapping(value = "/newProjectForm.html")
    public void newProjectForm(ProjectForm projectForm) {
        projectForm.setCustomers(customerRepo.findAll());
        projectForm.setProjectCategories(projectCatRepo.findAll());
    }

    @RequestMapping(value = "/newProject.html")
    public String newProject(ProjectForm projectForm, Map modelMap) {

        try {
            Project halfBuildedProject = ProjectAssembler.toDom(projectForm);
            OrgnizationEmployee orgEmployee = employeeService.findByEmployeeId(halfBuildedProject.getManagerEmpId());
            Project project = Project.newProject(userService.getUserFromSession(), halfBuildedProject, orgEmployee);

            projectRepo.saveAndFlush(project);
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            logger.error("", e);
            WebResponse.newInstance().setExceptionMsg(e).buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping(value = "/editProject.html")
    public String editProject(ProjectForm projectForm, Map modelMap) {

        try {
            Project updateProject = ProjectAssembler.toDom(projectForm);

            Project project = projectRepo.findOne(Long.valueOf(projectForm.getUpdatekey()));

            project.setCode(updateProject.getCode());
            project.setName(updateProject.getName());
            project.setCustomer(updateProject.getCustomer());
            project.setManagerEmpId(updateProject.getManagerEmpId());
            project.setStartDate(updateProject.getStartDate());
            project.setEndDate(updateProject.getEndDate());
            project.setCategory(updateProject.getCategory());
            project.setDescription(updateProject.getDescription());

            projectRepo.saveAndFlush(project);
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            logger.error("", e);
            WebResponse.newInstance().setExceptionMsg(e).buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping(value = "/removeProject.html")
    public String removeProject(long projectId) {
        projectService.removeProject(projectId);
        return "redirect:projectList.html";
    }

    @RequestMapping(value = "/editProjectMain.html")
    public void editProjectMain(Long projectId, Map modelMap) {
        modelMap.put("projectId", projectId);
        logger.info("/editProjectMain.html");
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/beforEditProjectBaseInfo.html")
    public void beforEditProjectBaseInfo(ProjectForm projectForm, Long projectId, Map modelMap) {
        Project project = projectRepo.findOne(projectId);

        projectForm.setCustomers(customerRepo.findAll());
        projectForm.setProjectCategories(projectCatRepo.findAll());
        projectForm.setCustomerIdSlt(project.getCustomer().getCode());
        projectForm.setProjectCategoryIdSlt(project.getCategory().getId().toString());

        modelMap.put("project", project);

        modelMap.put("manageName", employeeService.findByEmployeeId(project.getManagerEmpId()).getName());

    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/beforEditProjectOrg.html")
    public void beforEditProjectOrg(Long projectId, Map modelMap) {

        try {
            ProjectEmployee manager = projectService.findProjectManager(projectId);

            List<Map<String, Object>> treeMap = new ArrayList<Map<String, Object>>();
            List<ProjectEmployee> childs = manager.getChilds();

            MapDataAssembling dataAssembling = new JsTreeDataUtil.MapDataAssembling() {
                @Override
                public Map assembling(TreeNodeWithChilds entryNode) {
                    Map<String, Object> e = new HashMap<String, Object>();
                    ProjectEmployee projectEmployee = ((ProjectEmployee) entryNode);
                    e.put("id", projectEmployee.getEmpId());
                    e.put("pId", entryNode.getParent() != null ? ((ProjectEmployee) entryNode.getParent()).getEmpId() : 0);
                    e.put("name", entryNode.getName());
                    e.put("titleWithinTheProject", projectEmployee.getTitleWithinTheProject());
                    e.put("rankType", projectEmployee.getRankType());
                    return e;
                }
            };

            for (ProjectEmployee employee : childs) {
                JsTreeDataUtil.buildTree(employee, treeMap, dataAssembling);
            }

            treeMap.add(dataAssembling.assembling((ProjectEmployee) manager));
            ObjectMapper mapper = new ObjectMapper();
            modelMap.put("treeData", mapper.writeValueAsString(treeMap));

            modelMap.put("projectId", projectId);
            modelMap.put("manager", manager);
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    @RequestMapping(value = "/editProjectOrg.html")
    public String editProjectOrg(Long projectId, String jsonData, Map modelMap) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            ArrayList<Map> listData = mapper.readValue(jsonData, ArrayList.class);

            List<ProjectEmployeeRawTreeNode> projectEmployeesHierarchy = new ArrayList<ProjectEmployeeRawTreeNode>();
            for (Map object : listData) {

                ProjectEmployeeRawTreeNode e = new ProjectEmployeeRawTreeNode();

                e.setId(Long.valueOf(object.get("id").toString()));
                e.setEmpId(Long.valueOf(object.get("empId").toString()));
                e.setEmpName(object.get("empName").toString());

                if (object.get("titleWithinTheProject") != null) {
                    e.setTitleWithinTheProject(object.get("titleWithinTheProject").toString());
                }

                if (object.get("parentId") != null) {
                    e.setParentId(Long.valueOf(object.get("parentId").toString()));
                }

                if (object.get("rankType") != null) {
                    String rankType = object.get("rankType").toString();
                    if (rankType.equals(ProjectEmployeeRankType.LEVEL_EXECUTION.toString())) {
                        e.setRankType(ProjectEmployeeRankType.LEVEL_EXECUTION);
                    } else {
                        e.setRankType(ProjectEmployeeRankType.LEVEL_MANAGEMENT);
                    }
                }

                projectEmployeesHierarchy.add(e);
            }
            projectService.storeProjectEmloyeesHierarchy(projectId, projectEmployeesHierarchy);

            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            logger.error("", e);
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }
//    return "redirect:editProjectMain.html?projectId=" + projectId;

        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/beforEditProjectStores.html")
    public void beforEditProjectStores(long projectId, Map modelMap) {

//        List<ProjectStore> all = projectStoreRepository.findByProjectId(projectId);
//        List ids = new ArrayList();
//        for (ProjectStore ps : all) {
//            ids.add(ps.getChannel().getCode());
//        }
        modelMap.put("posKindList", posKindLegacyRepository.findAll());
        modelMap.put("sysPosKindList", posSysTypeLegacyRepository.findAll());
        modelMap.put("projectId", projectId);
//        modelMap.put("storeIds", ids);
        modelMap.put("storeIds", new ArrayList<String>(0));
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/projectStoresList.html")
    public void projectStoresList(long projectId, Pageable pageable, Map modelMap, HttpServletRequest request) {

//	  Page<ProjectStore> results = projectStoreRepository.findAll(ProjectAssembler.toCriteria(projectId), pageable);

        Page results = searchService.findProjectStore(RequestUtil.getParameterMap(request), pageable);

        modelMap.put("page", new PageHandler(pageable.getPageNumber(),
                Long.valueOf(results.getTotalElements()).intValue(),
                pageable.getPageSize(),
                results.getContent()));
    }

    /**
     * 添加关联项目门店
     *
     * @param projectId
     * @param storesId
     * @return
     * @author Yuqi Chou
     * @version Jun 19, 2012  11:07:44 AM
     */
    @RequestMapping(value = "/editProjectStores.html")
    public String editProjectStores(Map modelMap,
                                    @RequestParam(required = true) long projectId,
                                    @RequestParam(required = true) String storesId) {

        String[] ids = storesId.split(";");
        if (ids == null || storesId.length() < 1) {
            WebResponse.newInstance().buildModelMapData(modelMap);
            return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
        }

        List<ProjectStore> entities = new ArrayList<ProjectStore>();
        Project project = new Project();
        project.setId(projectId);
        for (int i = 0; i < ids.length; i++) {
            //Channel channel= basicService.findChannelBy(ids[i]);
            ChannelSync channelSync = channelSyncRepo.findByChannelCode(ids[i]);
            if (channelSync != null) {
                ProjectStore e = new ProjectStore(project, channelSync);
                entities.add(e);
            }
        }
        if (entities.size() > 0) {
            int successNum = projectService.saveProjectStore(entities);
            WebResponse res = WebResponse.newInstance();
            if (successNum != entities.size()) {
                res.setMsgBody("未添加重复门店");
            }
            res.buildModelMapData(modelMap);
        }

        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    /**
     * 删除项目门店
     *
     * @param projectId
     * @param projectStoreId
     * @return
     * @author Yuqi Chou
     * @version Jun 19, 2012  11:08:19 AM
     */
    @RequestMapping(value = "/removeProjectStores.html")
    public String editProjectStores(@RequestParam(required = true) long projectId,
                                    @RequestParam(required = true) long projectStoreId) {
        projectStoreRepository.delete(projectStoreId);
        return "redirect:editProjectMain.html?projectId=" + projectId;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/beforEditProjectStoresAssign.html")
    public void beforEditProjectStoresAssign(@RequestParam(required = true) long projectId,
                                             Map modelMap,
                                             HttpServletRequest request) {

        modelMap.put("titles", projectEmployeeRepository.findAllTitles(projectId));
        modelMap.put("projectId", projectId);

    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/beforEditProjectStoresAssignData.html")
    public void beforEditProjectStoresAssignData(@RequestParam(required = true) long projectId,
                                                 Map modelMap,
                                                 HttpServletRequest request) {

        List<ProjectEmployee> employees = projectEmployeeRepository.findAll(ProjectAssembler.toProjectEmployeeCriteria(RequestUtil.getParameterMap(request)));

        modelMap.put("employees", employees);
        modelMap.put("projectId", projectId);

    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/employeeAssignedStores.html")
    public void employeeAssignedStores(@RequestParam(required = true) long projectId,
                                       @RequestParam(required = true) long empId,
                                       Pageable pageable,
                                       Map modelMap) {

//	  User user=new User();
//	  user.setEmployee(employeeService.findByEmployeeId(empId));
//
//	  List<ProjectStore> preAssigned = projectService.findStoresPreAssignedToUserWithinTheProject(user, projectId);
//	  Page<ProjectStore> canBeAssigned = projectService.findCandidateProjectStoresWhichCanBeAssigned(projectId, pageable);
//
//	  modelMap.put("preAssigned", preAssigned);
//	  modelMap.put("canBeAssigned", canBeAssigned.getContent());

        modelMap.put("empId", empId);
        modelMap.put("projectId", projectId);
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/employeeAssignedStoresData.html")
    public void employeeAssignedStoresData(@RequestParam(required = true) long projectId,
                                           @RequestParam(required = true) long empId,
                                           Pageable pageable,
                                           Map modelMap,
                                           @RequestParam(required = false) String storeCode,
                                           @RequestParam(required = false) String storeName,
                                           @RequestParam(required = false) String hasAssigned) {

        User user = new User();
        user.setEmployee(employeeService.findByEmployeeId(empId));

        List<ProjectStore> preAssigned = Lists.newArrayList();
        List<ProjectStore> canBeAssigned = Lists.newArrayList();

        //bomb
        if ("0".equals(hasAssigned)) {
            canBeAssigned = projectService.findCandidateProjectStoresWhichCanBeAssigned(projectId, pageable).getContent();
        } else if ("1".equals(hasAssigned)) {
            preAssigned = projectService.findStoresPreAssignedToUserWithinTheProject(user, projectId);
        } else {
            canBeAssigned = projectService.findCandidateProjectStoresWhichCanBeAssigned(projectId, pageable).getContent();
            preAssigned = projectService.findStoresPreAssignedToUserWithinTheProject(user, projectId);
        }

        List<ProjectStore> canBeAssignedCopy = new ArrayList<ProjectStore>();
        for (ProjectStore projectStore : canBeAssigned) {
            canBeAssignedCopy.add(projectStore);
        }

        List<ProjectStore> preAssignedCopy = new ArrayList<ProjectStore>();
        for (ProjectStore projectStore : preAssigned) {
            preAssignedCopy.add(projectStore);
        }

        if (canBeAssignedCopy != null && canBeAssignedCopy.size() > 0) {
            for (int i = 0; i < canBeAssignedCopy.size(); i++) {
                ProjectStore projectStore = canBeAssignedCopy.get(i);
                if (StringUtils.hasText(storeCode)) {
                    if (!projectStore.getChannelCode().equals(storeCode)) {
                        canBeAssignedCopy.remove(i);
                        i--;
                    }
                }
                if (StringUtils.hasText(storeName)) {
                    if (projectStore.getChannel().getName().indexOf(storeName) == -1) {
                        canBeAssignedCopy.remove(i);
                        i--;
                    }
                }
            }
        }

        if (preAssignedCopy != null && preAssignedCopy.size() > 0) {
            for (int i = 0; i < preAssignedCopy.size(); i++) {
                ProjectStore projectStore = preAssignedCopy.get(i);
                if (StringUtils.hasText(storeCode)) {
                    if (!projectStore.getChannelCode().equals(storeCode)) {
                        preAssignedCopy.remove(i);
                        i--;
                    }
                }
                if (StringUtils.hasText(storeName)) {
                    if (projectStore.getChannel().getName().indexOf(storeName) == -1) {
                        preAssignedCopy.remove(i);
                        i--;
                    }
                }
            }
        }
        //bomb end

        modelMap.put("preAssigned", preAssignedCopy);
        modelMap.put("canBeAssigned", canBeAssignedCopy);
        modelMap.put("projectId", projectId);
    }

    @RequestMapping(value = "/assignStoresToProjectEmployee.html")
    @ResponseBody
    public Object assignStoresToProjectEmployee(@RequestParam(required = true) long projEmpId,
                                                @RequestParam(required = true) String storeIds) {
        Map<Object, Object> m = Maps.newHashMap();
        try {
            List<Long> targetStoreIds = Lists.newArrayList();
            String[] ids = storeIds.split(";");
            for (int i = 0; i < ids.length; i++) {
                targetStoreIds.add(Long.valueOf(ids[i]));
            }
            if (targetStoreIds.size() > 0) {
                projectService.assignStoresToProjectEmployee(projEmpId, targetStoreIds);
            }
            m.put("ok", true);
        } catch (Exception e) {
            logger.error("", e);
            m.put("failed", false);
        }
        return m;
    }

    @RequestMapping(value = "/unbindWithSpecifiedAssignedStore.html")
    @ResponseBody
    public Object unbindWithSpecifiedAssignedStore(@RequestParam(required = true) long projEmpId,
                                                   @RequestParam(required = true) long storeId) {
        Map<Object, Object> m = Maps.newHashMap();
        try {
            List<Long> targetStoreIds = Lists.newArrayList();
            targetStoreIds.add(storeId);
            projectService.unbindWithSpecifiedAssignedStore(projEmpId, targetStoreIds);
            m.put("ok", true);
        } catch (Exception e) {
            logger.error("", e);
            m.put("failed", false);
        }
        return m;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/beforEditProjectProducts.html")
    public void editProjectProducts(Long projectId, Map modelMap) {
        Project project = projectRepo.findWithProductsNeedToBeCollected(projectId);
        modelMap.put("project", project);

        List<CommonKVT> amountUnitList = commonKVTRepository.findByKey(CommonKVT.SELLING_UPLOAD_AMOUNT_UNIT);
        modelMap.put("amountUnitList", amountUnitList);

        MDCustomer customer = basicService.findMDCustomerByCustomerLegacy(project.getCustomer());
        modelMap.put("json_category", toZTreeJSON_category(customer));
        modelMap.put("json_brand", toZTreeJSON_brand(customer));
        modelMap.put("json_sku", toZTreeJSON_sku(customer));
        modelMap.put("SU_AMOUNT_OR_PRICE_REQUIRED", hint.get(HintKey.SU_AMOUNT_OR_PRICE_REQUIRED));
    }

    private String toZTreeJSON_category(MDCustomer customer) {
        Map<String, Object> customerNode = new HashMap<String, Object>();
        customerNode.put("name", customer.getName());
        customerNode.put("open", true);
        List<Map<String, Object>> categoryNodeList = new LinkedList<Map<String, Object>>();
        customerNode.put("children", categoryNodeList);
        Collection<MDCategory> categories = customer.getCategories();
        if (categories.size() != 0) {
            for (MDCategory category : categories) {
                Map<String, Object> categoryNode = new HashMap<String, Object>();
                categoryNodeList.add(categoryNode);
                categoryNode.put("code", category.getCode());
                categoryNode.put("name", category.getAlias() + "（" + category.getMemo() + "）");
            }
        } else {
            customerNode.put("isParent", true);
            customerNode.put("nocheck", true);
            customerNode.put("iconSkin", "gray");
        }
        try {
            return jsonMapper.writeValueAsString(customerNode);
        } catch (IOException e) {
            return "{'name':'读取错误'}";
        }
    }

    private String toZTreeJSON_brand(MDCustomer customer) {
        Map<String, Object> customerNode = new HashMap<String, Object>();
        customerNode.put("name", customer.getName());
        customerNode.put("open", true);
        List<Map<String, Object>> categoryNodeList = new LinkedList<Map<String, Object>>();
        customerNode.put("children", categoryNodeList);
        boolean hasBrands = false;
        for (MDCategory category : customer.getCategories()) {
            Map<String, Object> categoryNode = new HashMap<String, Object>();
            categoryNodeList.add(categoryNode);
            categoryNode.put("name", category.getAlias() + "（" + category.getMemo() + "）");
            List<Map<String, Object>> brandNodeList = new LinkedList<Map<String, Object>>();
            categoryNode.put("children", brandNodeList);
            Collection<MDBrand> brands = category.getBrands();
            if (brands.size() != 0) {
                for (MDBrand brand : brands) {
                    hasBrands = true;
                    Map<String, Object> brandNode = new HashMap<String, Object>();
                    brandNodeList.add(brandNode);
                    brandNode.put("code", brand.getCode());
                    brandNode.put("name", brand.getName());
                }
            } else {
                categoryNode.put("isParent", true);
                categoryNode.put("nocheck", true);
                categoryNode.put("iconSkin", "gray");
            }
        }
        if (!hasBrands) {
            customerNode.put("isParent", true);
            customerNode.put("nocheck", true);
            customerNode.put("iconSkin", "gray");
        }
        try {
            return jsonMapper.writeValueAsString(customerNode);
        } catch (IOException e) {
            return "{'name':'读取错误'}";
        }
    }

    private String toZTreeJSON_sku(MDCustomer customer) {
        Map<String, Object> customerNode = new HashMap<String, Object>();
        customerNode.put("name", customer.getName());
        customerNode.put("open", true);
        List<Map<String, Object>> categoryNodeList = new LinkedList<Map<String, Object>>();
        customerNode.put("children", categoryNodeList);
        boolean hasProducts = false;
        for (MDCategory category : customer.getCategories()) {
            Map<String, Object> categoryNode = new HashMap<String, Object>();
            categoryNodeList.add(categoryNode);
            categoryNode.put("name", category.getAlias() + "（" + category.getMemo() + "）");
            List<Map<String, Object>> brandNodeList = new LinkedList<Map<String, Object>>();
            categoryNode.put("children", brandNodeList);
            Collection<MDBrand> brands = category.getBrands();
            boolean hasBrands = false;
            if (brands.size() != 0) {
                for (MDBrand brand : brands) {
                    Map<String, Object> brandNode = new HashMap<String, Object>();
                    brandNodeList.add(brandNode);
                    brandNode.put("name", brand.getName());
                    List<Map<String, Object>> productNodeList = new LinkedList<Map<String, Object>>();
                    brandNode.put("children", productNodeList);
                    Collection<MDProduct> products = brand.getProducts();
                    if (products.size() != 0) {
                        hasBrands = true;
                        hasProducts = true;
                        for (MDProduct product : products) {
                            Map<String, Object> productNode = new HashMap<String, Object>();
                            productNodeList.add(productNode);
                            productNode.put("code", product.getCode());
                            productNode.put("name", product.getSku());
                        }
                    } else {
                        brandNode.put("isParent", true);
                        brandNode.put("nocheck", true);
                        brandNode.put("iconSkin", "gray");
                    }
                }
            }
            if (!hasBrands) {
                categoryNode.put("isParent", true);
                categoryNode.put("nocheck", true);
                categoryNode.put("iconSkin", "gray");
            }
        }
        if (!hasProducts) {
            customerNode.put("isParent", true);
            customerNode.put("nocheck", true);
            customerNode.put("iconSkin", "gray");
        }
        try {
            return jsonMapper.writeValueAsString(customerNode);
        } catch (IOException e) {
            return "{'name':'读取错误'}";
        }
    }

    @SuppressWarnings({"rawtypes"})
    @RequestMapping(value = "/findProductsInfoByLevel.html")
    @ResponseBody
    public Object findProductsInfoByLevel(Long projectId,
                                          String code,
                                          String pcode,
                                          int level,
                                          Map modelMap) {

        try {
            if (level == ProjectProductCollectionType.BRAND.ordinal()) {
                List<Brand> brands = basicService.findBrandsByCustomerAndBrandCateogry(pcode, code);
                return assembJsonData(brands.iterator(), code, level);
            } else if (level == ProjectProductCollectionType.CATEGORY.ordinal()) {
                Set<BrandCategory> brandCategory = basicService.findBrandCategoriesByCustomer(code);
                return assembJsonData(brandCategory.iterator(), code, level);
            } else if (level == ProjectProductCollectionType.SKU.ordinal()) {
                List<Product> products = basicService.findProductsByBrandCategoryAndBrand(pcode, code);
                return assembJsonData(products.iterator(), code, level);
            }
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private List assembJsonData(Iterator ite, String pcode, int level) {
        List list = Lists.newLinkedList();
        //{name:"${customer.name}", code:"${customer.code}",pcode:"",level:0,isParent:true}
        while (ite.hasNext()) {
            Map jsonData = Maps.newLinkedHashMap();
            ProjectProductData data = (ProjectProductData) ite.next();
            jsonData.put("name", data.getName());
            jsonData.put("code", data.getCode());
            jsonData.put("id", UUID.randomUUID().toString());
            jsonData.put("pcode", pcode);
            if (level < 2) {
                jsonData.put("level", level + 1);
                jsonData.put("isParent", true);
            }
            list.add(jsonData);
        }
        return list;
    }

    @RequestMapping(value = "/storeProjectProducts.html")
    public String storeProjectProducts(Long projectId,
                                       String collectionType,
                                       String productsSkuCodes,
                                       Map modelMap) {

        try {
            String[] codes = org.apache.commons.lang.StringUtils.split(productsSkuCodes, ";");
            List<String> codeList = Lists.newArrayList();
            Collections.addAll(codeList, codes);
            projectService.storeProjectProducts(projectId, ProjectProductCollectionType.valueOf(collectionType), codeList);
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            logger.error("", e);
            WebResponse.newInstance().setExceptionMsg(e).buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping("/saveProjectSellingUpload.html")
    public String saveProjectSellingUpload(Long projectId, String codeString, ProjectProductCollectionType uploadType,
                                           boolean uploadSummary, boolean uploadAmount, String uploadAmountUnit, boolean uploadPrice,
                                           Map<String, Object> modelMap) {
        try {
            Project project = projectRepo.findOne(projectId);
            ProjectSellingUpload projectSellingUpload = projectSellingUploadRepository.findByProject_Id(projectId);
            if (projectSellingUpload == null) {
                projectSellingUpload = new ProjectSellingUpload();
            }
            String[] codes = org.apache.commons.lang.StringUtils.split(codeString, ';');
            projectSellingUpload.setProject(project);
            projectSellingUpload.setUploadType(uploadType);
            projectSellingUpload.getCodes().clear();
            projectSellingUpload.getCodes().addAll(Arrays.asList(codes));
            projectSellingUpload.setUploadSummary(uploadSummary ? 1 : 0);
            projectSellingUpload.setUploadAmount(uploadAmount ? 1 : 0);
            projectSellingUpload.setUploadAmountUnit(uploadAmountUnit);
            projectSellingUpload.setUploadPrice(uploadPrice ? 1 : 0);
            projectSellingUploadRepository.save(projectSellingUpload);
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance().setExceptionMsg(ExceptionHelper.getPreSaveValidateException(e)).buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings("unchecked")
    @RequestMapping("/projectbrowserList.html")
    public void projectbrowserList(Map modelMap) {
        modelMap.put("projectList", projectService.findByUserOwn(userService.getUserFromSession()));
    }

    @SuppressWarnings("unchecked")
    @RequestMapping("/projectSalesPromoterList.html")
    public void salesPromoterList(Map modelMap,
                                  Long projectId,
                                  Pageable pageable) {
        Page<ProjectSalesPromoter> results = projSalesPromRepo.findByProjectId(projectId, pageable);
        PageHandler p = new PageHandler(pageable.getPageNumber(), Long.valueOf(results.getTotalElements()).intValue(),
                pageable.getPageSize(), results.getContent());
        modelMap.put("page", p);
    }

    @SuppressWarnings("unchecked")
    @RequestMapping("/salesPromoterListData.html")
    public void salesPromoterListData(Map modelMap,
                                      Long projectId,
                                      Pageable pageable) {

        Page<SalesLegacy> results = salesLegacyRepository.findAll(pageable);
        PageHandler p = new PageHandler(pageable.getPageNumber(),
                Long.valueOf(results.getTotalElements()).intValue(),
                pageable.getPageSize(), results.getContent());
        if (projectId != null) {
            modelMap.put("projSalesProm", projSalesPromRepo.findByProjectId(projectId));
        }
        modelMap.put("page", p);
    }

    @RequestMapping("/addSalesPromoterToProject.html")
    public String addSalesPromoterToProject(Map modelMap,
                                            Long projectId,
                                            String salesPromoterList) {
        try {
            Project project = projectRepo.findOne(projectId);
            String[] salesPromoterIds = salesPromoterList.split(",");
            boolean foundDuplicateSales = false;
            for (String id : salesPromoterIds) {
                SalesLegacy salesLegacy = salesLegacyRepository.findOne(id);
                ProjectSalesPromoter psp = new ProjectSalesPromoter(project, salesLegacy);
                try {
                    projSalesPromRepo.saveAndFlush(psp);
                } catch (DataIntegrityViolationException e) {
                    logger.warn("重复添加促销员", e);
                    foundDuplicateSales = true;
                    continue;
                }
            }
            if (foundDuplicateSales) throw new RuntimeException("不允许重复添加促销员");

            WebResponse.newInstance().buildModelMapData(modelMap);

        } catch (Exception e) {
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);

            logger.error("", e);
        }

        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping("/delSalesPromoter.html")
    public String addSalesPromoterToProject(Map modelMap, Long salesPromoterId) {
        try {
            projSalesPromRepo.delete(salesPromoterId);
            WebResponse.newInstance().buildModelMapData(modelMap);
            return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
        } catch (Exception e) {
            logger.error("", e);
            WebResponse.newInstance().setExceptionMsg(e).buildModelMapData(modelMap);
            return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping("/salesPromoterAssignedStores.html")
    public void salesPromoterAssignedStores(Map modelMap, Long projectId, String saleId) {

        modelMap.put("salePromoter", salesLegacyRepository.findOne(saleId));
        beforEditProjectStores(projectId, modelMap);
    }

    /**
     * 查找项目促销员
     *
     * @param modelMap
     * @param projectId
     * @param pageable
     * @param request
     * @author Yuqi Chou
     * @version Aug 30, 2012  2:16:24 PM
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping("/projectSalesPromoterAssignListData.html")
    public void projectSalesPromoterAssignListData(Map modelMap, Long projectId, Pageable pageable, HttpServletRequest request) {

        Page<SalesLegacy> results = projectService.findSalesPromoter(RequestUtil.getParameterMap(request), pageable);

        for (SalesLegacy salesLegacy : results.getContent()) {
            AdminDivisionLegacy ad = adminDivisionLegacyRepository.findById(salesLegacy.getAdId());
            StringBuffer adStr = new StringBuffer();
            adStr.append(ad.getParentProvinceAdName());
            adStr.append(ad.getParentCityAdName());
            adStr.append(ad.getName());
            salesLegacy.setAdName(adStr.toString());
        }

        PageHandler p = new PageHandler(pageable.getPageNumber(),
                Long.valueOf(results.getTotalElements()).intValue(),
                pageable.getPageSize(),
                results.getContent());
        modelMap.put("page", p);
        modelMap.put("projectId", projectId);
    }

    /**
     * 促销员查询
     *
     * @param modelMap
     * @param request
     * @param projectId
     * @author Yuqi Chou
     * @version Aug 29, 2012  6:56:17 PM
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping("/beforEditProjectSalesPromoterAssign.html")
    public void beforEditProjectSalesPromoterAssign(Map modelMap, HttpServletRequest request, String projectId) {

        modelMap.put("projectId", projectId);
        modelMap.put("posKindList", posKindLegacyRepository.findAll());
        modelMap.put("sysPosKindList", posSysTypeLegacyRepository.findAll());

        modelMap.put("allStores", projectStoreRepository.findByProjectId(Long.valueOf(projectId)));

        modelMap.put("provinceList", adminDivisionLegacyRepository.findByDeep(1));

    }

    @ResponseBody
    @RequestMapping("/salesPromoterSalesPromoterAssign.html")
    public Object salesPromoterSalesPromoterAssign(String action,
                                                   Long projSalesId,
                                                   String storeIds,
                                                   String projectId) {
        List<Long> targetStoreIds = Lists.newArrayList();
        try {
            for (String id : storeIds.split(";")) {
                targetStoreIds.add(Long.valueOf(id));
            }

            Project project = projectRepo.findOne(Long.valueOf(projectId));

            ProjectSalesPromoter sp = projSalesRepo.findByProjectCodeAndSalesPromoterCode(project.getCode(), projSalesId.toString());

            if (sp == null) {
                return WebResponse.newInstance().setSuccess(false);
            }

            if ("bind".equals(action)) {
                if (targetStoreIds.size() > 0) {
                    //失败
                    List<ProjectStore> preStores = projectService.findStoresPreAssignedToSalesWithinTheProject(sp.getSalesPromoter().getCode(), Long.valueOf(projectId));
                    for (ProjectStore projectStore : preStores) {
                        if (!targetStoreIds.contains(projectStore.getId())) {
                            targetStoreIds.add(projectStore.getId());
                        }
                    }

                    projectService.assignStoresToProjectSalesPromoter(sp.getId(), targetStoreIds);
                }
            } else if ("unbind".equals(action)) {
                projectService.unbindProjectSalesWithSpecifiedAssignedStore(sp.getId(), targetStoreIds);
            }
            return WebResponse.newInstance();
        } catch (Exception e) {
            logger.error("", e);
            return WebResponse.newInstance().setExceptionMsg(e);
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/salesPromoterAssignedStoresListData.html")
    public void salesPromoterAssignedStores(@RequestParam(required = true) long projectId,
                                            String saleId,
                                            Pageable pageable,
                                            Map modelMap,
                                            HttpServletRequest request) {

        Page<Map> results = searchService.findProjectStore(RequestUtil.getParameterMap(request), pageable);

        List<String> storeCodes = Lists.newArrayList();
        for (Map store : results.getContent()) {
            storeCodes.add(store.get("ID").toString());
        }

        //筛选出当前页分配过的门店id
        modelMap.put("assignedIds", projectService.filterStoreIdsBySaleAssigned(storeCodes, saleId, projectId));
        modelMap.put("page", new PageHandler(pageable.getPageNumber(),
                Long.valueOf(results.getTotalElements()).intValue(),
                pageable.getPageSize(),
                results.getContent()));

    }

    @RequestMapping("/beforEditProjectImportantTask.html")
    public void beforEditProjectImportantTask(Long projectId, Map<String, Object> modelMap) {
        List<ProjectCriticalJob> projectCriticalJobs = projectCriticalJobRepository.findByProject_Id(projectId);
        modelMap.put("projectId", projectId);
        modelMap.put("jobs", projectCriticalJobs);
    }

    @RequestMapping("/deleteProjectCriticalJob.html")
    public String deleteProjectCriticalJob(Long criticalJobId, Map<String, Object> modelMap) {
        try {
            projectCriticalJobRepository.delete(criticalJobId);
        } catch (Exception ignore) {
        }
        WebResponse.newInstance().setSuccess(true).buildModelMapData(modelMap);
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/saveProjectCriticalJob.html")
    public String saveProjectCriticalJob(String projectCriticalJobData, Long projectId, Map modelMap) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            List<Map> saveData = mapper.readValue(projectCriticalJobData, ArrayList.class);
            Project project = projectRepo.findOne(projectId);

            for (Map obj : saveData) {
                ProjectCriticalJob entity = new ProjectCriticalJob();
                entity.setProject(project);
                entity.setJob(Job.findById(Long.valueOf(obj.get("jobId").toString())));
                entity.setEndTime(DateUtils.parseDate(obj.get("startTime").toString(), new String[]{"yyyy-MM-dd"}));
                entity.setStartTime(DateUtils.parseDate(obj.get("startTime").toString(), new String[]{"yyyy-MM-dd"}));

                projectCriticalJobRepository.save(entity);
            }

            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (DataIntegrityViolationException e) {
            logger.error("", e);
            WebResponse.newInstance()
                    .setSuccess(false)
                    .setMsgBody("不能重复添加重点任务")
                    .buildModelMapData(modelMap);
        } catch (Exception e) {
            logger.error("", e);
            WebResponse.newInstance().setExceptionMsg(e).buildModelMapData(modelMap);
        }

        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping("/projectStoreAssignSales.html")
    public void projectStoreAssignSales(@RequestParam("projectStoreId") long projectStoreId, Map<String, Object> modelMap) {
        ProjectStore projectStore = projectStoreRepository.findOne(projectStoreId);
        modelMap.put("projectStoreId", projectStoreId);
        modelMap.put("requiredSalesNumber", projectStore.getRequiredSalesNumber());
        modelMap.put("thisYear", new DateTime().getYear());
    }

    @RequestMapping("/updateProjectStoreRequiredSalesNumber.html")
    public String projectStoreRequiredSalesNumber(@RequestParam long projectStoreId,
                                                  @RequestParam int requiredSalesNumber,
                                                  @RequestParam int sellingTargetYear,
                                                  @RequestParam String sellingTargetDataString,
                                                  Map<String, Object> modelMap) {
        try {
            ProjectStore projectStore = projectStoreRepository.findOne(projectStoreId);
            projectStore.setRequiredSalesNumber(requiredSalesNumber);
            projectStoreRepository.save(projectStore);
            Map<Integer, Integer> yearMonthValues = new HashMap<Integer, Integer>();
            for (String monthValueString : org.apache.commons.lang.StringUtils.split(sellingTargetDataString, ';')) {
                String[] ss = org.apache.commons.lang.StringUtils.split(monthValueString, ':');
                yearMonthValues.put(Integer.parseInt(ss[0]), Integer.parseInt(ss[1]));
            }
            sellingUpload.saveTargetValues(projectStoreId, sellingTargetYear, yearMonthValues);
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance().setExceptionMsg(ExceptionHelper.getPreSaveValidateException(e)).buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping("/getProjectStoreSellingTarget.html")
    @ResponseBody
    public String getProjectStoreSellingTarget(@RequestParam long projectStoreId, @RequestParam int year) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            List<ProjectStoreSellingTargetValue> targetValues = sellingUpload.getTargetValues(projectStoreId, year);
            for (ProjectStoreSellingTargetValue targetValue : targetValues) {
                map.put(String.valueOf(targetValue.getYearMonth() % 100), targetValue.getSummary());
            }
            map.put("year", year);
            map.put("placeholder", sellingUpload.getSummary(projectStoreId, year - 1, 12));
            return jsonMapper.writeValueAsString(map);
        } catch (Exception e) {
            return "{year:" + year + ", placeholder:0}";
        }
    }

    @RequestMapping("/sellingUploadList.html")
    public void sellingUploadList(Map<String, Object> modelMap) {
        List<PosKindLegacy> channelTypeList = posKindLegacyRepository.findAll(new Sort("name"));
        List<PosSysTypeLegacy> channelSystemList = posSysTypeLegacyRepository.findAll(new Sort("name"));
        modelMap.put("channelTypeList", channelTypeList);
        modelMap.put("channelSystemList", channelSystemList);
        modelMap.put("provinceList", adminDivisionLegacyRepository.findByDeep(1));
    }

    @RequestMapping("/sellingUploadListData.html")
    public void sellingUploadListData(String projectCode, String projectName, String channelCode, String channelName,
                                      String adCode, String channelType, String channelSystem,
                                      @DateTimeFormat(pattern = "yyyy-MM-dd") Date dateFrom,
                                      @DateTimeFormat(pattern = "yyyy-MM-dd") Date dateTo,
                                      Pageable pageable, Map<String, Object> model) {
        User user = userService.getCurrentUserWithPermissionRoleAndEntries();
        Page page = sellingUpload.findMySellingUpload(pageable, user,
                projectCode, projectName, channelCode, channelName,
                adCode, channelType, channelSystem, dateFrom, dateTo);
        PageHandler pageHandler = new PageHandler(pageable.getPageNumber(), (int) page.getTotalElements(), pageable.getPageSize(), page.getContent());
        model.put("page", pageHandler);
    }
}
